package util;


import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;

/**
 * @author fanfanglei
 * @date 2022/10/8 11:58 上午
 * @desc
 */
public class ExportUtils {

    public static <T> SXSSFWorkbook createExcel(Map<String, String> head, List<T> dataList) {
        String sheetName = head.remove("_sheetName");
        SXSSFWorkbook wb = new SXSSFWorkbook();
        Sheet sheet;
        Row row;
        //添加边框线
        CellStyle alignStyle = wb.createCellStyle();
        alignStyle.setBorderBottom(BorderStyle.THIN);
        alignStyle.setBorderTop(BorderStyle.THIN);
        alignStyle.setBorderLeft(BorderStyle.THIN);
        alignStyle.setBorderRight(BorderStyle.THIN);
        if (StringUtils.isNotBlank(sheetName)) {
            sheet = wb.createSheet(sheetName);
        } else {
            sheet = wb.createSheet();
        }
        row = sheet.createRow(sheet.getLastRowNum() + 1);
        List<Entry<String, String>> entryList = mapToList(head);
        //生成标题
        for (int j = 0; j < entryList.size(); j++) {
            Map.Entry<String, String> entry = entryList.get(j);
            row.createCell(j).setCellValue(entry.getValue());
            //设置样式
            row.getCell(j).setCellStyle(alignStyle);
        }
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (int i = 0; dataList.size() > i; i++) {
                T data = dataList.get(i);
                Class<?> dataClass = data.getClass();
                row = sheet.createRow(sheet.getLastRowNum() + 1);
                for (int j = 0; j < entryList.size(); j++) {
                    Map.Entry<String, String> entry = entryList.get(j);
                    try {
                        Field declaredField = dataClass.getDeclaredField(entry.getKey());
                        declaredField.setAccessible(true);
                        Object objValue = declaredField.get(data);
                        if (objValue != null) {
                            if (objValue instanceof Date) {
                                JsonFormat jsonFormat = declaredField.getAnnotation(JsonFormat.class);
                                String pattern = "yyyy-MM-dd HH:mm:ss";
                                if (jsonFormat != null && StringUtils.isNotBlank(jsonFormat.pattern())) {
                                    pattern = jsonFormat.pattern();
                                }
                                row.createCell(j).setCellValue(DateUtils.formatDateToString((Date) objValue, pattern));
                            } else {
                                row.createCell(j).setCellValue(String.valueOf(objValue));
                            }
                        } else {
                            row.createCell(j).setCellValue("");
                        }
                        //设置样式
                        row.getCell(j).setCellStyle(alignStyle);
                    } catch (Exception e) {
                        System.out.println(e);
                    }
                }
            }
        }
        return wb;
    }

    protected static <T> List<Map.Entry<String, T>> mapToList(Map<String, T> headMap) {
        List<Map.Entry<String, T>> entryList = new ArrayList();
        Iterator iter = headMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            entryList.add(entry);
        }
        return entryList;
    }


    public static SXSSFWorkbook createExcel(List<ExcelSheetInfo> sheets){
        SXSSFWorkbook wb=new SXSSFWorkbook();
        for (ExcelSheetInfo sheetInfo:sheets){
            createExcel(wb,sheetInfo);
        }
        return wb;
    }


    public static <T> SXSSFWorkbook createExcel(SXSSFWorkbook wb ,ExcelSheetInfo<T> sheetInfo) {
        if(wb==null){
            wb=new SXSSFWorkbook();
        }
        Sheet sheet=wb.createSheet(sheetInfo.getSheetName());
        String headDesc = sheetInfo.getHeadDesc();
        List<T> dataList = sheetInfo.getDatas();
        List<ExcelSheetColInfo> cols = sheetInfo.getCols();
        Row row;
        //添加边框线
        CellStyle alignStyle = wb.createCellStyle();
        alignStyle.setBorderBottom(BorderStyle.THIN);
        alignStyle.setBorderTop(BorderStyle.THIN);
        alignStyle.setBorderLeft(BorderStyle.THIN);
        alignStyle.setBorderRight(BorderStyle.THIN);

        //合并填写描述
        if(StringUtils.isNotEmpty(headDesc)){
            row = sheet.createRow(sheet.getLastRowNum() + 1);
            row.setHeight((short)2000);
            Cell cell = row.createCell(0);
            //设置高度
            cell.setCellValue(headDesc);
            //内容自动换行
            CellStyle cellStyle = wb.createCellStyle();
            cellStyle.setWrapText(true);
            cell.setCellStyle(cellStyle);
            //合并单元格
            CellRangeAddress cellAddresses = new CellRangeAddress(0, 0, 0, cols.size() - 1);
            sheet.addMergedRegion(cellAddresses);

        }

        int headRowNUm = sheet.getLastRowNum() + 1;
        row = sheet.createRow(headRowNUm);
        //创建批注对象 可能用到
        Drawing drawingPatriarch = sheet.createDrawingPatriarch();
        CreationHelper factory=wb.getCreationHelper();
        //设置样式


        List<CellStyle> cellStyles=new ArrayList<>();
        //生成标题
        for (int j = 0; j < cols.size(); j++) {
            ExcelSheetColInfo colInfo = cols.get(j);
            Cell cell = row.createCell(j);
            cell.setCellValue(colInfo.getHeadName());

            //设置批注
            if(StringUtils.isNotEmpty(colInfo.getHeadComment())) {
                ClientAnchor anchor=factory.createClientAnchor();
             /*   Comment cellComment1 = drawingPatriarch.createCellComment(anchor);
                RichTextString hello = factory.createRichTextString(colInfo.getHeadComment());
                cellComment1.setString(hello);
                cell.setCellComment(cellComment1);*/
       /*         anchor.setRow1(row.getRowNum());
                anchor.setRow2(row.getRowNum()+2);
                anchor.setCol1(cell.getColumnIndex());
                anchor.setCol2(cell.getColumnIndex()+4);
                Comment cellComment = drawingPatriarch.createCellComment(anchor);
                cellComment.setString(factory.createRichTextString(colInfo.getHeadComment()+2));
                cellComment.setAuthor("cf");
                cell.setCellComment(cellComment);
*/
                Comment cellComment1 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, cell.getColumnIndex(), cell.getRowIndex(),cell.getColumnIndex()+4,cell.getRowIndex()+4));
                cellComment1.setString(new XSSFRichTextString(colInfo.getHeadComment()));
                cell.setCellComment(cellComment1);
/*
                XSSFClientAnchor xssfClientAnchor = new XSSFClientAnchor();
                xssfClientAnchor.setRow1(headRowNUm);
                xssfClientAnchor.setCol1(j);
                Comment cellComment = drawingPatriarch.createCellComment(xssfClientAnchor);
                cellComment.setString(new XSSFRichTextString(colInfo.getHeadComment()));
                cell.setCellComment(cellComment);*/
            }


            if(StringUtils.isNotEmpty(cols.get(j).getStyle())){
                CellStyle cellStyle = wb.createCellStyle();
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                DataFormat dataFormat = wb.createDataFormat();
                cellStyle.setDataFormat(dataFormat.getFormat(cols.get(j).getStyle()));
                cellStyles.add(cellStyle);
            }else{
                cellStyles.add(alignStyle);
            }

            row.getCell(j).setCellStyle(alignStyle);
        }
        sheet.createFreezePane(0,headRowNUm+1);
            if (CollectionUtils.isNotEmpty(dataList)) {
                for (int i = 0; dataList.size() > i; i++) {
                    T data = dataList.get(i);
                    Class<?> dataClass = data.getClass();
                    row = sheet.createRow(sheet.getLastRowNum() + 1);
                    for (int j = 0; j < cols.size(); j++) {
                        CellStyle cellStyle = cellStyles.get(j);
                        ExcelSheetColInfo colInfo = cols.get(j);
                        try {
                            extracted(row, cellStyle, data, dataClass, j, colInfo);
                        } catch (Exception e) {
                            System.out.println(e);
                            e.printStackTrace();
                            try {
                                //对于父类字段的反射调用
                                extracted(row, cellStyle, data, dataClass.getSuperclass(), j, colInfo);
                            }catch (Exception ef){
                                System.out.println(e);
                            }

                        }
                    }
                }
            }
        return wb;
    }

    private static <T> void extracted(Row row, CellStyle alignStyle, T data, Class<?> dataClass, int j, ExcelSheetColInfo colInfo) throws NoSuchFieldException, IllegalAccessException {
        Field declaredField = dataClass.getDeclaredField(colInfo.getColumnName());
        declaredField.setAccessible(true);
        Object objValue = declaredField.get(data);
        if (objValue != null) {
            if (objValue instanceof Date) {
                JsonFormat jsonFormat = declaredField.getAnnotation(JsonFormat.class);
                String pattern = "yyyy-MM-dd HH:mm:ss";
                if (jsonFormat != null && StringUtils.isNotBlank(jsonFormat.pattern())) {
                    pattern = jsonFormat.pattern();
                }
                row.createCell(j).setCellValue(DateUtils.formatDateToString((Date) objValue, pattern));
            } else {
                if(StringUtils.isNotEmpty(colInfo.getStyle())) {
                    row.createCell(j).setCellValue(Double.valueOf(String.valueOf(objValue)));
                }else {
                    row.createCell(j).setCellValue(String.valueOf(objValue));
                }
            }
        } else {
            row.createCell(j).setCellValue("");
        }

        //设置样式
        row.getCell(j).setCellStyle(alignStyle);

    }

}